package com.wkk.yuli.util;

import com.alibaba.fastjson.JSONObject;
import com.wkk.yuli.bo.Disappear;
import com.wkk.yuli.common.Constant;
import com.wkk.yuli.config.ContainerConfig;
import com.wkk.yuli.core.Container;
import lombok.extern.slf4j.Slf4j;

import java.io.*;
import java.util.concurrent.ConcurrentHashMap;

/**
 * @author : WangKeKe
 * @date : 2020/9/24 15:32
 * Description : 封装一些常用的方法
 */

@Slf4j
@SuppressWarnings("all")
public class ToolUtils {

    /**
     * 判断是否过期
     *
     * @param value 带过期时间戳的值 Disappear类型值
     * @return 未过期 返回内容 过期返回 - 移除 并返回null
     */
    public static Object judgeDisappear(Object value) {
        Disappear disappear = JSONObject.parseObject((String) value, Disappear.class);
        Long disappearTime = disappear.getExpireTime();
        Long systemTime = System.currentTimeMillis();
        // 如果为-1L 则代表永久  或者过期时间未到
        return (disappearTime == -1L || disappearTime - systemTime > 0) ?
                disappear.getValue() :
                removeObject(disappear.getKey());
    }

    /**
     * 移除key和其对应的值
     *
     * @param key 键值
     */
    private static Object removeObject(Object key) {
        if (ContainerConfig.EXPIRE_PURGE_POLICY.equals(Constant.EXPIRE_PURGE_POLICY_PASSIVE)) {
            // 被动删除 - 访问到过期 才删除
            Container.getYuLi().remove(key);
            // 文件刷新 - 快照持久化
            push();
        }
        return null;
    }

    public static boolean push() {
        // 如果配置文件打开了 持久化
        // - 每次快照 只要进行一次set remove操作就 需要 将容器内容与文件内容
        // - 如果开启每秒快照 需要此方法不执行方法体
        if (ContainerConfig.PERSISTENCE_STATUS.equals(Constant.PERSISTENCE_STATUS_OPEN)
                && ContainerConfig.PERSISTENCE_POLICY.equals(Constant.PERSISTENCE_POLICY_FREQUENCY)) {
            pushTxtInMap(Container.getYuLi(), ContainerConfig.PERSISTENCE_FILE_LOCATION, ContainerConfig.PERSISTENCE_FILE_NAME);
            return true;
        }
        return false;
    }

    public static void pushTime() {
        pushTxtInMap(Container.getYuLi(), ContainerConfig.PERSISTENCE_FILE_LOCATION, ContainerConfig.PERSISTENCE_FILE_NAME);
    }

    public static ConcurrentHashMap<Object, Object> pull() {
        return pullFromTxt(new ConcurrentHashMap<>(ContainerConfig.UPPER_LIMIT_SIZE), ContainerConfig.PERSISTENCE_FILE_LOCATION, ContainerConfig.PERSISTENCE_FILE_NAME);
    }

    /**
     * 将Map内容输出到txt文件中 - 快照写法RDB
     *
     * @param fileLocation 文件地址
     * @param fileName     文件名
     * @param map          内容
     */
    private static void pushTxtInMap(ConcurrentHashMap<Object, Object> map, String fileLocation, String fileName) {
        FileOutputStream fileOutputStream = null;
        ObjectOutputStream objectOutputStream = null;
        try {
            fileOutputStream = new FileOutputStream(new File(fileLocation + fileName));
            objectOutputStream = new ObjectOutputStream(fileOutputStream);
            objectOutputStream.writeObject(map);
            objectOutputStream.flush();
        } catch (Exception e) {
            log.info("出现异常了：" + e.getMessage());
        } finally {
            if (objectOutputStream != null) {
                try {
                    objectOutputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (fileOutputStream != null) {
                try {
                    fileOutputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    /**
     * 读取文件中的内容并写入Map中
     *
     * @param fileName     文件名
     * @param fileLocation 文件地址
     * @param map          容器
     * @return map 结果
     */
    private static ConcurrentHashMap<Object, Object> pullFromTxt(ConcurrentHashMap<Object, Object> map, String fileLocation, String fileName) {
        FileInputStream fileInputStream = null;
        ObjectInputStream objectInputStream = null;
        try {
            fileInputStream = new FileInputStream(new File(fileLocation + fileName));
            objectInputStream = new ObjectInputStream(fileInputStream);
            map = (ConcurrentHashMap<Object, Object>) objectInputStream.readObject();
        } catch (Exception e) {
            log.info("出现异常了：" + e.getMessage());
        } finally {
            if (objectInputStream != null) {
                try {
                    objectInputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (fileInputStream != null) {
                try {
                    fileInputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        return map;
    }

    /**
     * 清空文件内容
     *
     * @param fileLocation 文件路径
     * @param fileName     文件名称
     */
    private static void clearInfoForFile(String fileLocation, String fileName) {
        File file = new File(fileLocation + fileName);
        try {
            if (!file.exists()) {
                file.createNewFile();
            }
            FileWriter fileWriter = new FileWriter(file);
            fileWriter.write("");
            fileWriter.flush();
            fileWriter.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}
